
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "StreamType.h"

/********************* 整数处理函数 **************************/

static unsigned int ReadNumberOfBits(int size)
{
    unsigned int val = 0;
    int bit = size;
    while (bit  > 0) {
        int num = 8 - InOut->bit;
        if (num > bit) {
            num = bit;
        }

        int mask = (1 << num) - 1;
        if (InOut->sort == TQ_BIG) {
            val <<= num;
            val |= (InOut->buf[InOut->pos] >> (8 - InOut->bit - num)) & mask;
        } else {
            val |= ((InOut->buf[InOut->pos] >> InOut->bit) & mask) << (size - bit);
        }

        InOut->bit += num;
        bit -= num;
        if (InOut->bit >= 8) {
            InOut->bit -= 8;
            InOut->pos++;
        }
    }
    return val;
}

static unsigned char ReadByte(int size)
{
    if (InOut->bit == 0 && size == 8) {
        return InOut->buf[InOut->pos++];
    }
    return (unsigned char) ReadNumberOfBits(size);
}

static unsigned short ReadShort(int size)
{
    if (InOut->bit == 0 && size == 16) {
        unsigned short val = InOut->buf[InOut->pos];
        if (InOut->sort == TQ_BIG) {
            val <<= 8;
            val |= InOut->buf[InOut->pos + 1];
        } else {
            val |= InOut->buf[InOut->pos + 1] << 8;
        }
        InOut->pos += 2;
        return val;
    }
    return (unsigned short) ReadNumberOfBits(size);
}

static unsigned int ReadInt(int size)
{
    if (InOut->bit == 0 && size == 32) {
        unsigned int val = InOut->buf[InOut->pos];
        if (InOut->sort == TQ_BIG) {
            val <<= 8;
            val |= InOut->buf[InOut->pos + 1];
            val <<= 8;
            val |= InOut->buf[InOut->pos + 2];
            val <<= 8;
            val |= InOut->buf[InOut->pos + 3];
        } else {
            val |= InOut->buf[InOut->pos + 1] << 8;
            val |= InOut->buf[InOut->pos + 2] << 16;
            val |= InOut->buf[InOut->pos + 3] << 24;
        }
        InOut->pos += 4;
        return val;
    }
    return ReadNumberOfBits(size);
}

static unsigned long long ReadLong(int size)
{
    unsigned long long val;
    int bit = size;

    int num = 32 - InOut->bit;
    val = ReadInt(num);
    bit -= num;

    num = (bit > 32) ? 32 : bit;
    if (InOut->sort == TQ_BIG) {
        val <<= num;
        val |= ReadInt(num);
    } else {
        val |= ((unsigned long long) ReadInt(num)) << (size - bit);
    }
    bit -= num;

    num = bit;
    if (num > 0) {
        if (InOut->sort == TQ_BIG) {
            val <<= num;
            val |= ReadInt(num);
        } else {
            val |= ((unsigned long long) ReadInt(num)) << (size - bit);
        }
    }
    return val;
}

long long ReadNumber()
{
    unsigned long long val = 0;
    if (InOut->size <= 0) {
        ThrowError(- __LINE__);
    } else if (InOut->size <= 8) {
        val = ReadByte(InOut->size);
    } else if (InOut->size <= 16) {
        val = ReadShort(InOut->size);
    } else if (InOut->size <= 32) {
        val = ReadInt(InOut->size);
    } else if (InOut->size <= 64) {
        val = ReadLong(InOut->size);
    } else {
        ThrowError(- __LINE__);
    }
    if (InOut->sign == TQ_SIGN && (val & (1 << (InOut->size - 1)))) {
        return val - ((long long) 1 << InOut->size);
    }
    return val;
}

static void WriteNumberOfBits(unsigned int val, int size)
{
    int bit = size;
    while (bit  > 0) {
        int num = 8 - InOut->bit;
        if (num > bit) {
            num = bit;
        }

        int mask = (1 << num) - 1;
        if (InOut->sort == TQ_BIG) {
            InOut->buf[InOut->pos] &= ~(mask << (8 - InOut->bit - num));
            InOut->buf[InOut->pos] |= (unsigned char) (((val >> (bit - num)) & mask) << (8 - InOut->bit - num));
        } else {
            InOut->buf[InOut->pos] &= ~(mask << InOut->bit);
            InOut->buf[InOut->pos] |= (unsigned char) ((val & mask) << InOut->bit);
            val >>= num;
        }

        InOut->bit += num;
        bit -= num;
        if (InOut->bit >= 8) {
            InOut->bit -= 8;
            InOut->pos++;
        }
    }
}

static void WriteByte(unsigned char val, int size)
{
    if (InOut->bit == 0 && size == 8) {
        InOut->buf[InOut->pos++] = val;
    } else {
        WriteNumberOfBits(val, size);
    }
}

static void WriteShort(unsigned short val, int size)
{
    if (InOut->bit == 0 && size == 16) {
        if (InOut->sort == TQ_BIG) {
            InOut->buf[InOut->pos++] = (unsigned char) (val >> 8);
            InOut->buf[InOut->pos++] = (unsigned char) val;
        } else {
            InOut->buf[InOut->pos++] = (unsigned char) val;
            InOut->buf[InOut->pos++] = (unsigned char) (val >> 8);
        }
    } else {
        WriteNumberOfBits(val, size);
    }
}

static void WriteInt(unsigned int val, int size)
{
    if (InOut->bit == 0 && size == 32) {
        if (InOut->sort == TQ_BIG) {
            InOut->buf[InOut->pos++] = (unsigned char) (val >> 24);
            InOut->buf[InOut->pos++] = (unsigned char) (val >> 16);
            InOut->buf[InOut->pos++] = (unsigned char) (val >> 8);
            InOut->buf[InOut->pos++] = (unsigned char) val;
        } else {
            InOut->buf[InOut->pos++] = (unsigned char) val;
            InOut->buf[InOut->pos++] = (unsigned char) (val >> 8);
            InOut->buf[InOut->pos++] = (unsigned char) (val >> 16);
            InOut->buf[InOut->pos++] = (unsigned char) (val >> 24);
        }
    } else {
        WriteNumberOfBits(val, size);
    }
}

static void WriteLong(unsigned long long val, int size)
{
    int num = 32 - InOut->bit;
    if (InOut->sort == TQ_BIG) {
        WriteInt(val >> (size - num), num);
    } else {
        WriteInt(val, num);
        val >>= num;
    }
    size -= num;

    num = (size > 32) ? 32 : size;
    if (InOut->sort == TQ_BIG) {
        WriteInt(val >> (size - num), num);
    } else {
        WriteInt(val, num);
        val >>= num;
    }
    size -= num;

    num = size;
    if (num > 0) {
        WriteInt(val, num);
    }
}

void WriteNumber(long long val)
{
    unsigned long long val0;
    if (InOut->sign == TQ_SIGN && val < 0) {
        val0 = val + ((long long) 1 << InOut->size);
    } else {
        val0 = val;
    }

    if (InOut->size <= 0) {
        ThrowError(- __LINE__);
    } else if (InOut->size <= 8) {
        WriteByte(val0, InOut->size);
    } else if (InOut->size <= 16) {
        WriteShort(val0, InOut->size);
    } else if (InOut->size <= 32) {
        WriteInt(val0, InOut->size);
    } else if (InOut->size <= 64) {
        WriteLong(val0, InOut->size);
    } else {
        ThrowError(- __LINE__);
    }
}

const char *Number2Str(long long val)
{
    static char numBuf[20];
    if (val < 0) {
        sprintf(numBuf, "%ld", (long) val);
    } else if (((long) val) == val) {
        sprintf(numBuf, "0x%lX", (long) val);
    } else {
        sprintf(numBuf, "0x%lX%08lX", (long) (val >> 32), (long) val);
    }
    return numBuf;
}

/************************** 小数处理函数 ********************************/

double ReadDecimal()
{
    if (InOut->size == 32) {
        unsigned int buf = ReadInt(32);
        return *(float*) &buf;
    } else if (InOut->size == 64) {
        unsigned long long buf = ReadLong(64);
        return *(double*) &buf;
    } else {
        ThrowError(- __LINE__);
    }
    return 0;
}

void WriteDecimal(double val)
{
    if (InOut->size == 32) {
        float buf = val;
        WriteInt(*(unsigned int*) &buf, 32);
    } else if (InOut->size == 64) {
        WriteLong(*(unsigned long long*) &val, 64);
    } else {
        ThrowError(- __LINE__);
    }
}

const char *Decimal2Str(double val)
{
    static char numBuf[20];
    sprintf(numBuf, "%lg", val);
    return numBuf;
}

/************************** 通用处理函数 ********************************/

void PrintString(const char *str, int len)
{
    int realLen = 0;
    while (str[realLen] != '\0' && realLen < len) realLen++;

    if (realLen < len) {
        PrintLabelValue(str, T_Print);
    } else {
        char strBuf[1025];
        while (realLen > 1024) {
            memcpy(strBuf, str, 1024);
            strBuf[1024] = '\0';
            PrintLabelValue(strBuf, T_Print);
            realLen -= 1024;
            str += 1024;
        }

        memcpy(strBuf, str, realLen);
        strBuf[realLen] = '\0';
        PrintLabelValue(strBuf, T_Print);
    }
}

void PrintBytes(const unsigned char *bytes, int len)
{
    char strBuf[50], *ptr;
    if (len > 32) len = 32;
    int i;
    for (i = 0; i < len; i++) {
        ptr = strBuf + i % 16 * 3;
        sprintf(ptr, " %02X", bytes[i]);
        if (i % 16 == 15) {
            strBuf[48] = '\0';
            PrintLabelValue(strBuf, T_Print);
        }
    }
    if (i % 16) {
        strBuf[i % 16 * 3] = '\0';
        PrintLabelValue(strBuf, T_Print);
    }
}

void PrintTimeDate(void *time, int type)
{
    if (type != T_Print) return;
    struct tm *t = localtime((time_t*) time);
    char strBuf[30];
    sprintf(strBuf, "%d/%d/%d %d:%d:%d",
        t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
        t->tm_hour, t->tm_min, t->tm_sec);
    PrintLabelValue(strBuf, T_Print);
}

/************************** 输入/输出属性配置函数 ********************************/

void SetPos(int pos)
{
    InOut->pos = pos;
    InOut->bit = 0;
}

void SetSize(int size)
{
    InOut->size = size;
}

void SetAlign(int align)
{
    if (align == 0) return;
    if (InOut->bit != 0) {
        InOut->bit = 0;
        InOut->pos++;
    }
    InOut->pos = (InOut->pos + align - 1) / align * align;
}

int SetSign(int sign)
{
    int old = InOut->sign;
    InOut->sign = sign;
    return old;
}

int SetSort(int sort)
{
    int old = InOut->sort;
    InOut->sort = sort;
    return old;
}

int Available(void)
{
    return InOut->pos < InOut->len;
}

/************************** 公共函数 ********************************/

typedef struct block
{
    struct block *next;
    int size;
    char ptr[0];
} Block;

Block *HeadBlock = NULL, *LastBlock = NULL;

void *GetPosBuf(int pos)
{
    return &InOut->buf[pos];
}

int GetMaxCount(int baseSize)
{
    return (InOut->len - InOut->pos); // / baseSize;
}

int GetBufferSize(void *buf)
{
    int *tmp = (int*) buf;
    return tmp[-1];
}

void *ST_Alloc(int size)
{
    Block *p = (Block*) malloc(sizeof(Block) + size);
    if (p == NULL) {
        ThrowError(- __LINE__);
    }
    p->size = size;
    p->next = NULL;

    if (HeadBlock == NULL) {
        HeadBlock = p;
    } else {
        LastBlock->next = p;
    }
    LastBlock = p;

    return p->ptr;
}

void ST_FreeAll(void)
{
    Block *p = HeadBlock, *q;
    while (p != NULL) {
        q = p;
        p = p->next;
        free(q);
    }
    HeadBlock = NULL;
    LastBlock = NULL;
}

/************************** 接口函数示例 ********************************/

#if 0

#include <stdarg.h>

typedef struct {
    void (*FreeAllBuffer) (void);
    void (*ThrowError)(int errCode);
    void (*Log)(int type, const char *format, va_list arg);

    void (*PrintLevelAdd)(int type);
    void (*PrintLevelSub)(int type);
    void (*PrintLabelKey)(const char *key, int type);
    void (*PrintLabelValue)(const char *val, int type);
    void (*PrintLabelEndKey)(int type);
} StreamApi;

__declspec(dllexport) InOutStreamType InOutStream = {0, 0, 0, 0, TQ_UNSIGN, TQ_LITTLE, NULL};
__declspec(dllexport) StreamApi streamApi = {ST_FreeAll, NULL};
InOutStreamType *InOut = &InOutStream;

void ThrowError(int errCode)
{
    if (streamApi.ThrowError != NULL) {
        streamApi.ThrowError(errCode);
    } else {
        printf("StreamApi is null, error line at %d\n", errCode);
        exit(102);
    }
}

void Log(int type, const char *format, ...)
{
    if (streamApi.Log != NULL) {
        va_list arg;
        va_start(arg, format);
        streamApi.Log(type, format, arg);
        va_end(arg);
    } else {
        ThrowError(- __LINE__);
    }
}

void PrintLevelAdd(int type)
{
    if (streamApi.PrintLevelAdd != NULL) {
        streamApi.PrintLevelAdd(type);
    } else {
        ThrowError(- __LINE__);
    }
}

void PrintLevelSub(int type)
{
    if (streamApi.PrintLevelSub != NULL) {
        streamApi.PrintLevelSub(type);
    } else {
        ThrowError(- __LINE__);
    }
}

void PrintLabelKey(const char *key, int type)
{
    if (streamApi.PrintLabelKey != NULL) {
        streamApi.PrintLabelKey(key, type);
    } else {
        ThrowError(- __LINE__);
    }
}

void PrintLabelValue(const char *val, int type)
{
    if (streamApi.PrintLabelValue != NULL) {
        streamApi.PrintLabelValue(val, type);
    } else {
        ThrowError(- __LINE__);
    }
}

void PrintLabelEndKey(int type)
{
    if (streamApi.PrintLabelEndKey != NULL) {
        streamApi.PrintLabelEndKey(type);
    } else {
        ThrowError(- __LINE__);
    }
}

#endif
